<template>
  <el-main class="vertical">
    <el-container style="height:55%;">
      <basic-crud :option="option" ref="basicCrudRef" @row-click="handleRowClick" businessUrl="/ui/codeRuleController"
        v-model:formData="rCodeFormData">
        <template #status="{ row, label }">
          <el-tag v-if="row.status === 'Enabled'" type="success">{{
            label
          }}</el-tag>
          <el-tag v-if="row.status === 'Disabled'" type="info">{{
            label
          }}</el-tag>
        </template>
        <template #menu="{ row }">
          <el-button link @click="handleOpenEdit(row, index)" type="primary" icon="Edit">编辑</el-button>

          <el-button link type="primary" v-if="row.status === 'Disabled'"
            @click="handleToggleStatus(row, 'Enabled')">启用</el-button>
          <el-button link type="primary" v-if="row.status === 'Enabled'"
            @click="handleToggleStatus(row, 'Disabled')">停用</el-button>
          <el-button @click="handlDel(row)" link type="danger" v-if="row.status === 'Disabled'"
            icon="Delete">删除</el-button>
        </template>
      </basic-crud>
    </el-container>
    <el-container style="height:45%;">
      <avue-crud v-model="formData" :option="detailOption" :data="tableData" :table-loading="tableLoading"
        @row-save="handleAddDetail" @row-update="handleEditDetail" :before-open="detailOpenBefore"
        ref="basicCrudDetailRef">
        <template #status="{ row, label }">
          <el-tag v-if="row.status === 'Enabled'" type="success">{{
            label
          }}</el-tag>
          <el-tag v-if="row.status === 'Disabled'" type="info">{{
            label
          }}</el-tag>
        </template>
        <template #menu="{ row, index }">
          <el-button link type="primary" @click="handlDelMove(row, 'up')" :loading="row.loading">上移</el-button>
          <el-button link type="primary" @click="handlDelMove(row, 'down')" :loading="row.loading">下移</el-button>
          <el-button v-if="row.codeElementType === 'code_element_enum'" link type="primary" icon="Edit"
            @click="handleOpenMenuDialog(row, index)">枚举设置</el-button>
          <el-button link @click="handleOpenDetailEdit(row, index)" type="primary" icon="Edit">编辑</el-button>

          <el-button @click="handlDetailDel(row)" link type="danger" icon="Delete">删除</el-button>
        </template>
      </avue-crud>
    </el-container>

    <basic-dialog v-model="visible" title="枚举设置" :auto-close="false" :submitBtnLoading="submitBtnLoading"
      @submit="handleSetEnum">
      <avue-crud :option="enumOption" :data="enumTable">
        <template #menu-left>
          <basic-crud-table-select v-model:formData="enumFormData" placeholder="请选择枚举值" label="枚举值" :crudProps="{
            width: '60%',
            dataType: 'emun',
            option: {
              searchSpan: 8,
              height: '45vh',
            },
          }" :comProps="{
            comType: 'direct',
            showField: 'name',
            saveFieldMap: { name: 'name', code: 'code' },
          }" :rules="[
            {
              required: true,
              message: '值对应的属性不能为空',
              trigger: 'change',
            },
          ]" @submit="handleSubmitEnum"></basic-crud-table-select>
        </template>
        <template #codeMapValue="{ row, disabled }">
          <el-input v-model="row.codeMapValue" :disabled="disabled"></el-input>
        </template>
        <template #menu="{ row }">
          <el-button link @click="handleDetailEnum(row)" v-if="row.id" style="color: red">删除</el-button>
        </template>
      </avue-crud>
    </basic-dialog>
  </el-main>
</template>

<script setup>
import {
  apiDel,
  apiEnable,
  apiDisable,
  apiGetToolCodeDetailList,
  apiGetToolCodeDetailAdd,
  apiToolCodeDetaiEdit,
  apiToolCodeDetaiDel,
  apiToolCodeDetaiMove,
  apiAddOrEditEnum,
  apiGetReceiptCodeRulesDetailEnumList,
  apiGetReceiptCodeRulesDetailEnumDel,
} from '@/apis/uiEngine/codeRuleManage/receiptCodeRule.js'
import { apiGetEnumByCode } from '@/apis/objectModel/enumData.js'
import { trueFalseDic } from '@/config/enum.js'
import { computed } from 'vue'
const adminHeight = ref((document.body.clientHeight - 120) * 0.45 - 75);//0.45是父容器的高度设为45%

const basicCrudRef = ref()
const rCodeFormData = ref({})
const option = {
  viewBtn: true,
  searchSpan: 6,
  editBtn: false,
  menuWidth: 210,
  calcHeight: adminHeight.value + 100,
  highlightCurrentRow: true,
  delBtn: false,
  labelWidth: 150,
  column: [
    {
      label: '编号',
      prop: 'code',
      sortable: true,
      search: true,
      searchSpan: 6,
      span: 12,
      minWidth: 100,
      placeholder: '编号不能重复',
      rules: [{ required: true, message: '编号不能为空' }],
    },
    {
      prop: 'name',
      label: '规则名称',
      search: true,
      minWidth: 100,
      searchSpan: 6,
      span: 12,
      rules: [{ required: true, message: '名称不能为空' }],
    },
    {
      prop: 'busName',
      label: '所属业务类型',
      span: 12,
      width: 150,
      component: 'BasicCrudTableSelect',
      dataType: 'bus',
      comProps: {
        saveFieldMap: { busName: 'name', busCode: 'code' },
        selectedKey: 'code',
      },
      curForm: rCodeFormData,
      change: (newV) => {
        rCodeFormData.value = newV
      },
      rules: [
        { required: true, message: '所属业务类型不能为空', trigger: 'change' },
      ],
    },
    {
      label: '所属部门',
      prop: 'deptIdName',
      component: 'BasicCrudTableSelect',
      dataType: 'dept',
      width: 150,
      comProps: {
        saveFieldMap: { deptIdName: 'name', deptId: 'id' },
        selectedKey: 'id'
      },
      curForm: rCodeFormData,
      change: (newV) => {
        rCodeFormData.value = newV
      },
    },
    {
      prop: 'totalLength',
      label: '总长度',
      span: 12,
      disabled: true,
      minWidth: 100,
      value: 1,
      display: false,
      hide: true
    },
    {
      prop: 'codeAfterFlag',
      label: '是否后编码',
      span: 12,
      minWidth: 100,
      type: 'switch',
      value: 'true',
      dicData: trueFalseDic,
    },
    {
      prop: 'useRuleFlag',
      label: '使用规则标记',
      span: 12,
      minWidth: 200,
    },
    {
      prop: 'codeEditFlag',
      label: '是否可以编辑',
      span: 12,
      minWidth: 120,
      type: 'switch',
      dicData: trueFalseDic,
    },
    {
      prop: 'breakReUseFlag',
      label: '是否断码补码',
      span: 12,
      minWidth: 120,
      type: 'switch',
      dicData: trueFalseDic,
    },
    {
      label: '状态',
      prop: 'status',
      display: false,
      type: 'select',
      width: 100,
      search: true,
      searchSpan: 6,

      dicData: [
        {
          label: '已启用',
          value: 'Enabled',
        },
        {
          label: '已停用',
          value: 'Disabled',
        },
      ],
    },
  ],
}

const handleOpenEdit = (row, index) => {
  basicCrudRef.value.crudRef.rowEdit(row, index)
}

const handlDel = (row) => {
  ElMessageBox.confirm('确认删除该条数据？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
    beforeClose: async (action, instance, done) => {
      if (action === 'confirm') {
        instance.confirmButtonLoading = true
        apiDel(row.id)
          .then(() => {
            ElMessage.success('删除成功！')
            basicCrudRef.value.getList()
          })
          .finally((res) => {
            instance.confirmButtonLoading = false
          })
      } else {
        done()
      }
    },
  })
}

const curRow = ref({})
const handleRowClick = async (row) => {
  curRow.value = row
  getDetailList()
}

// 状态切换
const handleToggleStatus = (row, type) => {
  let apiFun = apiEnable
  let text = '发布'
  if (type === 'Disabled') {
    apiFun = apiDisable
    text = '停用'
  }
  ElMessageBox.confirm(`确认${text}该数据?`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
    beforeClose: async (action, instance, done) => {
      if (action === 'confirm') {
        instance.confirmButtonLoading = true
        apiFun(row)
          .then(() => {
            ElMessage.success(`${text}成功！`)
            done()
            basicCrudRef.value.getList()
          })
          .finally(() => {
            instance.confirmButtonLoading = false
          })
      } else {
        done()
      }
    },
  })
}

const useDetail = () => {
  // 明细数据
  const basicCrudDetailRef = ref()
  const tableData = ref([])
  const formData = ref({})
  const tableLoading = ref(false)
  // 新增按钮是否显示
  const isAdd = computed(() => !!curRow.value?.id)
  // 元素类型映射
  const codeElementTypeMap = {
    code_element_enum: [
      'maxLength',
      'minLength',
      'codeFillType',
      'codeFillSeparator',
      'codeUseFieldName',
      'serialAccording',
    ],
    code_element_date: [
      'maxLength',
      'minLength',
      'codeFillType',
      'codeFillSeparator',
      'codeDateFormat',
      'codeDateValueType',
      'codeDateUseFieldName',
      'serialAccording',
    ],
    code_element_field: [
      'maxLength',
      'minLength',
      'codeFillType',
      'codeFillSeparator',
      'codeUseFieldName',
      'serialAccording',
    ],
    code_element_serial: [
      'maxLength',
      'minLength',
      'codeFillType',
      'codeFillSeparator',
      'serialStart',
      'serialStep',
      'serialPriority',
    ],
    code_element_expression: [
      'maxLength',
      'minLength',
      'codeFillType',
      'codeFillSeparator',
      'codeExpression',
    ],
    code_element_static: ['serialAccording', 'staticCode'],
  }
  const detailOption = ref({
    viewBtn: true,
    addBtn: isAdd,
    editBtn: false,
    menuWidth: 250,
    height: adminHeight.value,
    highlightCurrentRow: true,
    page: false,
    delBtn: false,
    labelWidth: 150,
    dialogWidth: '1000',
    selection: false,
    column: [
      {
        label: '元素类型',
        prop: 'codeElementType',
        span: 12,
        width: 120,
        type: 'select',
        value: 'code_element_enum',
        dicData: [
          {
            label: '枚举属性映射',
            value: 'code_element_enum',
          },
          {
            label: '日期',
            value: 'code_element_date',
          },
          {
            label: '属性',
            value: 'code_element_field',
          },
          {
            label: '流水号',
            value: 'code_element_serial',
          },
          {
            label: '公式',
            value: 'code_element_expression',
          },
          {
            label: '常量',
            value: 'code_element_static',
          },
        ],
        change: ({ value }) => {
          let props = [
            'maxLength',
            'minLength',
            'codeFillType',
            'codeFillSeparator',
            'codeDateFormat',
            'codeDateValueType',
            'codeDateValueTypeText',
            'codeExpression',
            'serialAccording',
            'staticCode',
            'serialStart',
            'serialStep',
            'serialPriority',
            'codeDateUseFieldName',
            'codeUseFieldName',
          ]
          let propList = codeElementTypeMap[value]
          detailOption.value.column.forEach((item) => {
            if (props.includes(item.prop)) {
              item.display = false
            }
            if (propList.includes(item.prop)) {
              item.display = true
            }
          })
        },
        rules: [{ required: true, message: '元素类型不能为空' }],
      },
      {
        label: '元素编号',
        prop: 'code',
        span: 12,
        width: 120,
        rules: [{ required: true, message: '元素编号不能为空' }],
      },
      {
        label: '元素中文名',
        prop: 'name',
        span: 12,
        width: 120,
        rules: [{ required: true, message: '元素中文名不能为空' }],
      },

      {
        label: '最大长度',
        prop: 'maxLength',
        span: 12,
        width: 120,
        type: 'number',
        rules: [{ required: true, message: '最大长度不能为空' }],
      },
      {
        label: '最小长度',
        prop: 'minLength',
        span: 12,
        width: 120,
        type: 'number',
        rules: [{ required: true, message: '最小长度不能为空' }],
      },
      {
        label: '编码补位方式',
        prop: 'codeFillType',
        span: 12,
        type: 'select',
        width: 120,
        dicData: [
          {
            label: '不补位',
            value: 'code_fill_none',
          },
          {
            label: '左补位',
            value: 'code_fill_left',
          },
          {
            label: '右补位',
            value: 'code_fill_right',
          },
        ],
        rules: [{ required: true, message: '编码补位方式不能为空' }],
      },
      {
        label: '补位字符',
        prop: 'codeFillSeparator',
        span: 12,
        width: 120,
      },
      {
        label: '时间格式',
        prop: 'codeDateFormat',
        span: 12,
        width: 120,

        rules: [{ required: true, message: '时间格式不能为空' }],
      },
      {
        label: '时间取值类型',
        prop: 'codeDateValueType',
        span: 12,
        width: 120,
        type: 'select',
        dicData: [
          {
            label: '业务时间',
            value: 'code_date_business',
          },
          {
            label: '系统时间',
            value: 'code_date_system',
          },
        ],
        change: ({ value }) => {
          detailOption.value.column.forEach((item) => {
            if (item.prop === 'codeDateUseFieldName') {
              if (value === 'code_date_business') {
                item.display = true
              } else {
                item.display = false
              }
            }
          })
          if (value === 'code_date_system') {

          }
        },
        rules: [{ required: true, message: '时间取值类型不能为空' }],
      },
      {
        label: '时间取值属性',
        prop: 'codeDateUseFieldName',
        rules: [
          {
            required: true,
            message: '时间取值属性不能为空',
            trigger: 'change',
          },
        ],
      },
      {
        label: '值对应的属性',
        prop: 'codeUseFieldName',
        rules: [
          {
            required: true,
            message: '值对应的属性不能为空',
            trigger: 'change',
          },
        ],
      },
      {
        label: '公式表达式',
        prop: 'codeExpression',
        span: 12,
        width: 120,

        rules: [{ required: true, message: '公式表达式不能为空' }],
      },
      {
        label: '常量的值',
        prop: 'staticCode',
        span: 12,
        width: 120,
        rules: [{ required: true, message: '常量的值不能为空' }],
      },
      {
        label: '是否流水依据',
        prop: 'serialAccording',
        value: 'false',
        span: 12,
        width: 120,
        type: 'switch',
        dicData: trueFalseDic,
      },

      {
        label: '流水起始值',
        prop: 'serialStart',
        span: 12,
        width: 120,
        value: 1,
        rules: [{ required: true, message: '流水起始值不能为空' }],
      },
      {
        label: '流水步长',
        prop: 'serialStep',
        span: 12,
        type: 'number',
        value: 1,
        width: 120,
        rules: [{ required: true, message: '流水步长不能为空' }],
      },
      {
        label: '流水优先级',
        prop: 'serialPriority',
        span: 12,
        width: 120,
        value: 1,
        type: 'number',
        rules: [{ required: true, message: '流水优先级不能为空' }],
      },
    ],
  })

  // 弹窗打开之前
  const detailOpenBefore = (done, type, loading) => {
    if (curRow.value.codeAfterFlag === 'false') {
      detailOption.value.column[0]['dicData'] = detailOption.value.column[0][
        'dicData'
      ].map((item) => {
        if (['code_element_enum', 'code_element_field'].includes(item.value)) {
          item.disabled = true
        }
        return item
      })
    } else {
      detailOption.value.column = detailOption.value.column.map((item) => {
        item.disabled = false
        return item
      })
    }
    done()
  }

  const getDetailList = async () => {
    const data = await apiGetToolCodeDetailList(
      { codeRuleId: curRow.value.id },
      tableLoading
    )
    tableData.value = data
  }
  // 新增详情
  const handleAddDetail = async (row, done, loading) => {
    let params = JSON.parse(JSON.stringify(row))
    params.autoCodeRuleId = curRow.value.id
    params.orderNum = tableData.value.length + 1
    if (params.codeElementType === 'code_element_static') {
      params.minLength = params.staticCode?.length || 0
      params.codeFillType = 'code_fill_none'
    }
    apiGetToolCodeDetailAdd(params)
      .then(() => {
        done()
        ElMessage.success('操作成功！')
        getDetailList()
      })
      .catch((err) => {
        ElMessage.error(err.msg)
      })
      .finally(() => {
        loading()
      })

    // row.parentId
  }
  // 删除详情
  const handlDetailDel = (row) => {
    ElMessageBox.confirm('确认删除该条数据？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
      beforeClose: async (action, instance, done) => {
        if (action === 'confirm') {
          instance.confirmButtonLoading = true
          apiToolCodeDetaiDel(row.id)
            .then(() => {
              ElMessage.success('删除成功！')
              getDetailList()
              done()
            })
            .finally((res) => {
              instance.confirmButtonLoading = false
            })
        } else {
          done()
        }
      },
    })
  }
  // 打开详情编辑
  const handleOpenDetailEdit = (row, index) => {
    basicCrudDetailRef.value.rowEdit(row, index)
  }
  // 编辑确定
  const handleEditDetail = (row, index, done, loading) => {
    apiToolCodeDetaiEdit(row)
      .then(() => {
        ElMessage.success('修改成功！')
        done(row)
        getDetailList()
      })
      .finally(() => {
        loading()
      })
  }
  // 移动
  const handlDelMove = (row, type) => {
    row.loading = true
    apiToolCodeDetaiMove(row, type)
      .then(() => {
        getDetailList()
      })
      .finally(() => {
        row.loading = false
      })
  }
  return {
    basicCrudDetailRef,
    codeElementTypeMap,
    detailOption,
    tableData,
    tableLoading,
    formData,
    getDetailList,
    handleAddDetail,
    handlDetailDel,
    handleOpenDetailEdit,
    handleEditDetail,
    handlDelMove,
    detailOpenBefore,
  }
}
const {
  basicCrudDetailRef,
  detailOption,
  tableData,
  tableLoading,
  formData,
  getDetailList,
  handleAddDetail,
  handlDetailDel,
  handleOpenDetailEdit,
  handleEditDetail,
  handlDelMove,
  detailOpenBefore,
} = useDetail()

const useenum = () => {
  const visible = ref(false)
  const curDetailRow = ref()
  const enumOption = {
    addBtn: false,
    height: '40vh',
    delBtn: false,
    rowKey: 'enumId',
    menu: false,
    menuWidth: '100',
    viewbtn: false,
    editBtn: false,
    selection: false,
    column: [
      {
        prop: 'code',
        label: '英文名',
      },
      {
        prop: 'name',
        label: '中文名',
      },
      {
        prop: 'enumItemKey',
        label: '枚举项的key',
      },
      {
        prop: 'enumItemValue',
        label: '枚举项的值',
      },
      {
        prop: 'codeMapValue',
        label: '在编码规则中的映射值',
        width: '200',
      },
    ],
  }
  const enumTable = ref([])
  const enumFormData = ref({})
  const submitBtnLoading = ref(false)
  const getDetailEnumList = async () => {
    let resData = []
    // 接口获取的之前保存的枚举
    const apiData = await apiGetReceiptCodeRulesDetailEnumList({
      autoCodeRuleId: curRow.value.id,
      codeRuleElementId: curDetailRow.value.id,
    })
    resData = apiData
    if (apiData.length > 0) {
      enumFormData.value = {
        name: apiData[0]['name'],
        code: apiData[0]['code'],
      }
      // 接口获取最新的枚举数据
      const allEnumData = await apiGetEnumByCode(apiData[0]['code'])
      let existKeys = apiData.map((item) => item.enumItemKey)
      let newEnumData = allEnumData.filter(
        (item) => !existKeys.includes(item.value)
      )
      resData = apiData.concat(formatEnumData(newEnumData))
      enumTable.value = resData
    }
  }
  // 枚举弹窗
  const handleOpenMenuDialog = async (row) => {
    enumTable.value = []
    curDetailRow.value = row
    getDetailEnumList()
    visible.value = true
  }
  const formatEnumData = (list) => {
    return list.map((item) => {
      return {
        enumId: item.id,
        code: enumFormData.value.code,
        name: enumFormData.value.name,
        enumItemKey: item.value,
        enumItemValue: item.label,
      }
    })
  }
  const handleSubmitEnum = async (row) => {
    const data = await apiGetEnumByCode(row.code)
    enumFormData.value = row
    enumTable.value = formatEnumData(data)
  }
  // 确认保存
  const handleSetEnum = () => {
    enumTable.value = enumTable.value.map((item) => {
      item.autoCodeRuleId = curRow.value.id
      item.codeRuleElementId = curDetailRow.value.id
      return item
    })
    submitBtnLoading.value = true
    apiAddOrEditEnum(enumTable.value)
      .then((res) => {
        ElMessage.success('操作成功！')
        getDetailList()
        visible.value = false
      })
      .finally(() => {
        submitBtnLoading.value = false
      })
  }
  // 删除枚举
  const handleDetailEnum = async (row) => {
    await apiGetReceiptCodeRulesDetailEnumDel(row.id)
    getDetailEnumList()
  }
  return {
    visible,
    enumOption,
    enumFormData,
    enumTable,
    submitBtnLoading,
    handleOpenMenuDialog,
    handleSubmitEnum,
    handleSetEnum,
    handleDetailEnum,
  }
}
const {
  visible,
  handleOpenMenuDialog,
  enumOption,
  enumFormData,
  enumTable,
  submitBtnLoading,
  handleSubmitEnum,
  handleSetEnum,
  handleDetailEnum,
} = useenum()
</script>

<style lang="scss" scoped></style>
